package com.immediatus.ui.view;

import com.immediatus.engine.collision.LineCollisionChecker;
import com.immediatus.engine.collision.RectangularCollisionChecker;
import com.immediatus.engine.collision.ShapeCollisionChecker;
import com.immediatus.engine.contracts.IShape;
import com.immediatus.engine.input.TouchEvent;
import com.immediatus.engine.primitive.Line;
import com.immediatus.engine.shape.RectangularShape;
import com.immediatus.engine.shape.Shape;
import com.immediatus.graphics.camera.Camera;
import com.immediatus.graphics.util.OpenGLWrapper;
import com.immediatus.graphics.vertex.RectangleVertexBuffer;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

public class Button extends Shape{

    private float _baseWidth;
    private float _baseHeight;
    private float _width;
    private float _height;
    private final RectangleVertexBuffer _vertexBuffer;

    private boolean _isPressed;

    public Button(final float x_, final float y_, final float w_, final float h_){
        super(x_, y_);

        this._isPressed = false;

        this._baseWidth = this._width = w_;
        this._baseHeight = this._height = h_;

        final float centerX = w_ * 0.5f;
        final float centerY = h_ * 0.5f;
        this.setRotationCenterX(centerX);
        this.setRotationCenterY(centerY);
        this.setScaleCenterX(centerX);
        this.setScaleCenterY(centerY);

        _vertexBuffer = new RectangleVertexBuffer(GL11.GL_STATIC_DRAW, true);
        this.updateVertexBuffer();
    }

    @Override
    public boolean onAreaTouched(TouchEvent event_, float x_, float y_){
        switch(event_.getAction()) {
            case TouchEvent.ACTION_DOWN:
                this._isPressed = true;
                onTouchDown(x_,y_);
                break;
            case TouchEvent.ACTION_MOVE:
                break;
            case TouchEvent.ACTION_UP:
                this._isPressed = false;
                onTouchUp(x_,y_);
                break;
        }
        return true;
    }

    @Override
    public float getWidth(){
        return this._width;
    }

    public void setWidth(final float w_){
        this._width = w_;
        this.updateVertexBuffer();
    }

    @Override
    public float getHeight(){
        return this._height;
    }

    public void setHeight(final float h_){
        this._height = h_;
        this.updateVertexBuffer();
    }

    public void setSize(final float w_, final float h_){
        this._width = w_;
        this._height = h_;
        this.updateVertexBuffer();
    }

    @Override
    public RectangleVertexBuffer getVertexBuffer(){
        return this._vertexBuffer;
    }

    @Override
    protected void onUpdateVertexBuffer(){
        this._vertexBuffer.update(this.getWidth(), this.getHeight());
    }

    @Override
    public float getBaseWidth(){
        return this._baseWidth;
    }

    @Override
    public float getBaseHeight(){
        return this._baseHeight;
    }

    public void setBaseSize(){
        if (this._width != this._baseWidth || this._height != this._baseHeight){
            this._width = this._baseWidth;
            this._height = this._baseHeight;
            this.updateVertexBuffer();
        }
    }

    @Override
    public void reset(){
        super.reset();
        this.setBaseSize();

        final float baseWidth = this.getBaseWidth();
        final float baseHeight = this.getBaseHeight();

        final float centerX = baseWidth * 0.5f;
        final float centerY = baseHeight * 0.5f;


        this.setRotationCenterX(centerX);
        this.setRotationCenterY(centerY);

        this.setScaleCenterX(centerX);
        this.setScaleCenterY(centerY);
    }

    @Override
    public boolean contains(final float x_, final float y_){
        return ShapeCollisionChecker.checkContains(this.fillVerticles(), 8, x_, y_);
    }

    @Override
    public float[] getLayerCenterCoordinates(){
        return this.convertLocalToLayerCoordinates(this._width * 0.5f, this._height * 0.5f);
    }

    @Override
    public boolean collidesWith(final IShape shape_){
        final float[] verticesA = this.fillVerticles();
        final float[] verticesB = new float[8];

        if (shape_ instanceof RectangularShape){
            final RectangularShape rectangularShape = (RectangularShape) shape_;
            RectangularCollisionChecker.fillVertices(rectangularShape, verticesB);
            return ShapeCollisionChecker.checkCollision(8, verticesA, 8, verticesB);
        } else if (shape_ instanceof Line){
            final Line line = (Line) shape_;
            LineCollisionChecker.fillVertices(line, verticesB);
            return ShapeCollisionChecker.checkCollision(8, verticesA, 8, verticesB);
        } else{
            return false;
        }
    }

    @Override
    protected boolean isCulled(final Camera camera_){
        final float x = this.getX();
        final float y = this.getY();
        return x > camera_.getMaxX() || y > camera_.getMaxY() || x + this.getWidth() < camera_.getMinX() ||
                y + this.getHeight() < camera_.getMinY();
    }

    @Override
    protected void drawVertices(final GL10 gl_, final Camera camera_){
        gl_.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    }

    @Override
    protected void onInitDraw(final GL10 gl_){
        super.onInitDraw(gl_);
        OpenGLWrapper.disableTextures(gl_);
        OpenGLWrapper.disableTexCoordArray(gl_);
    }

    public void onTouchDown(float x_, float y_) {

    }

    public void onTouchUp(float x_, float y_) {

    }

    public void onClick(float x_, float y_) {

    }

    private float[] fillVerticles(){
        final float[] vertices = new float[8];
        final float right = getWidth();
        final float bottom = getHeight();

        vertices[0 + VERTEX_INDEX_X] = 0;
        vertices[0 + VERTEX_INDEX_Y] = 0;
        vertices[2 + VERTEX_INDEX_X] = right;
        vertices[2 + VERTEX_INDEX_Y] = 0;
        vertices[4 + VERTEX_INDEX_X] = right;
        vertices[4 + VERTEX_INDEX_Y] = bottom;
        vertices[6 + VERTEX_INDEX_X] = 0;
        vertices[6 + VERTEX_INDEX_Y] = bottom;

        this.getLocalToLayerTransformation().transform(vertices);
        return vertices;
    }
}

